import util
import uix
import trinity
import xtriui
import bluepy
import uiutil
import blue
MODE_SOLARSYSTEM = 1
MODE_CONSTELLATION = 2
MODE_REGION = 3
MODE_UNIVERSE = 4
MODE_HIDE = 5
MODE_NOLINES = 6
nullV = trinity.TriVector(0.0, 0.0, 0.0)
identV = trinity.TriVector(1.0, 1.0, 1.0)
scaleDownCurve = trinity.TriVectorCurve()
scaleDownCurve.extrapolation = trinity.TRIEXT_CONSTANT
scaleDownCurve.AddKey(0.0, identV, nullV, nullV, trinity.TRIINT_HERMITE)
scaleDownCurve.AddKey(0.5, identV, nullV, nullV, trinity.TRIINT_HERMITE)
scaleDownCurve.AddKey(2.0, nullV, nullV, nullV, trinity.TRIINT_HERMITE)
scaleDownCurve.Sort()
scaleUpCurve = trinity.TriVectorCurve()
scaleUpCurve.extrapolation = trinity.TRIEXT_CONSTANT
scaleUpCurve.AddKey(0.0, nullV, nullV, nullV, trinity.TRIINT_HERMITE)
scaleUpCurve.AddKey(0.5, nullV, nullV, nullV, trinity.TRIINT_HERMITE)
scaleUpCurve.AddKey(1.0, identV, nullV, nullV, trinity.TRIINT_HERMITE)
scaleUpCurve.Sort()
hideCurve = trinity.TriScalarCurve()
hideCurve.extrapolation = trinity.TRIEXT_CONSTANT
hideCurve.AddKey(0.0, 1.0, 0.0, 0.0, trinity.TRIINT_CONSTANT)
hideCurve.AddKey(0.1, 0.0, 0.0, 0.0, trinity.TRIINT_CONSTANT)
hideCurve.Sort()
showCurve = trinity.TriScalarCurve()
showCurve.extrapolation = trinity.TRIEXT_CONSTANT
showCurve.AddKey(0.0, 1.0, 0.0, 0.0, trinity.TRIINT_CONSTANT)
showCurve.AddKey(0.1, 1.0, 0.0, 0.0, trinity.TRIINT_CONSTANT)
showCurve.Sort()
black = trinity.TriColor(0.0, 0.0, 0.0)
white = trinity.TriColor(1.0, 1.0, 1.0)
gray = trinity.TriColor(0.5, 0.5, 0.5)
whiteToBlack = trinity.TriColorCurve()
whiteToBlack.AddKey(0.0, white, black, black, trinity.TRIINT_HERMITE)
whiteToBlack.AddKey(2.0, black, black, black, trinity.TRIINT_HERMITE)
whiteToBlack.extrapolation = trinity.TRIEXT_CONSTANT
whiteToBlack.Sort()
blackToWhite = trinity.TriColorCurve()
blackToWhite.AddKey(0.0, black, black, black, trinity.TRIINT_HERMITE)
blackToWhite.AddKey(1.0, white, black, black, trinity.TRIINT_HERMITE)
blackToWhite.extrapolation = trinity.TRIEXT_CONSTANT
blackToWhite.Sort()
black.a = 0.0
white.a = 1.0
gray.a = 0.5
alphaCurveDown = trinity.TriColorCurve()
alphaCurveDown.AddKey(0.0, white, black, black, trinity.TRIINT_HERMITE)
alphaCurveDown.AddKey(0.5, white, black, black, trinity.TRIINT_HERMITE)
alphaCurveDown.AddKey(2.0, black, black, black, trinity.TRIINT_HERMITE)
alphaCurveDown.extrapolation = trinity.TRIEXT_CONSTANT
alphaCurveDown.Sort()
alphaCurveUp = trinity.TriColorCurve()
alphaCurveUp.AddKey(0.0, black, black, black, trinity.TRIINT_HERMITE)
alphaCurveUp.AddKey(0.1, black, black, black, trinity.TRIINT_HERMITE)
alphaCurveUp.AddKey(1.0, white, black, black, trinity.TRIINT_HERMITE)
alphaCurveUp.extrapolation = trinity.TRIEXT_CONSTANT
alphaCurveUp.Sort()
alphaCurveUpHalf = trinity.TriColorCurve()
alphaCurveUpHalf.AddKey(0.0, black, black, black, trinity.TRIINT_HERMITE)
alphaCurveUpHalf.AddKey(0.1, black, black, black, trinity.TRIINT_HERMITE)
alphaCurveUpHalf.AddKey(1.0, gray, black, black, trinity.TRIINT_HERMITE)
alphaCurveUpHalf.extrapolation = trinity.TRIEXT_CONSTANT
alphaCurveUpHalf.Sort()
alphaCurveDownHalf = trinity.TriColorCurve()
alphaCurveDownHalf.AddKey(0.0, gray, black, black, trinity.TRIINT_HERMITE)
alphaCurveDownHalf.AddKey(0.1, gray, black, black, trinity.TRIINT_HERMITE)
alphaCurveDownHalf.AddKey(1.0, black, black, black, trinity.TRIINT_HERMITE)
alphaCurveDownHalf.extrapolation = trinity.TRIEXT_CONSTANT
alphaCurveDownHalf.Sort()

class MapCloud(bluepy.WrapBlueClass('trinity.TriTransform')):
    __guid__ = 'xtriui.MapCloud'
    __persistvars__ = ['sr']

    def __init__(self):
        self.sr = uiutil.Bunch()
        self.wr = util.WeakRefAttrObject()
        self.frustrumCull = 0
        self.sorted = 0
        self.sr.colorCurve = trinity.TriColorCurve()
        self.sr.colorCurve.extrapolation = trinity.TRIEXT_CONSTANT
        black = trinity.TriColor()
        self.sr.colorCurve.AddKey(0.0, black, black, black, trinity.TRIINT_HERMITE)
        self.sr.colorCurve.AddKey(0.5, black, black, black, trinity.TRIINT_HERMITE)
        self.sr.colorCurve.Sort()
        self.sr.constellations = {}
        self.sr.solarsystemIDs = []
        self.sr.trackers = {}
        self.sr.labels = {}
        self.sr.isReady = []



    def Initialize(self, regionID, sizefactor):
        self.name = ('cloud_%s' % regionID)
        self.sr.id = regionID
        self.sr.sizefactor = sizefactor
        self.sr.colorCurve.keys[1].value = self.GetColor()
        labeltrackers = trinity.TriTransform()
        labeltrackers.name = 'labeltrackers'
        labeltrackers.frustrumCull = 0
        labeltrackers.pickable = 0
        labeltrackers.sorted = 0
        self.children.append(labeltrackers)
        self.sr.labeltrackers = labeltrackers



    def CreateLinesAndPoints(self, cloudType):
        cloudTf = trinity.TriTransform()
        cloudTf.name = ('__' + cloudType)
        cloudTf.object = trinity.TriParticleCloud()
        cloudTf.pickable = 0
        cloudTf.sorted = 0
        if (cloudType == 'points'):
            cloudTf.object.cloudType = trinity.TRICT_POINT
            cloudTf.object.shader = blue.os.LoadObject('res:/UI/Shader/particle_point.blue')
            cloudTf.object.shader.passes[0].textureStage0.colorOp = trinity.TRITOP_ADD
            cloudTf.object.shader.passes[0].textureStage0.colorArg0 = trinity.TRITA_DIFFUSE
            cloudTf.object.shader.passes[0].textureStage0.colorArg1 = trinity.TRITA_DIFFUSE
            del cloudTf.object.shader.shaderMaterials[:]
            cloudTf.object.shader.shaderMaterials.append(trinity.TriAniMaterial())
            cloudTf.object.shader.shaderMaterials[0].emissive.SetRGB(0.28, 0.29, 0.24)
        else:
            cloudTf.object.cloudType = trinity.TRICT_LINE
            cloudTf.object.shader = blue.os.LoadObject('res:/UI/Shader/particle_line.blue')
            del cloudTf.object.shader.shaderMaterials[:]
            cloudTf.object.shader.shaderMaterials.append(trinity.TriAniMaterial())
            cloudTf.object.shader.shaderMaterials[0].emissiveCurve = self.sr.colorCurve
        cloudTf.object.shader.passes[0].materialSource = trinity.TRIMATSRC_SHADER
        if (cloudType == 'lines'):
            cloudTf.object.shader.passes[0].fog = 1
            cloudTf.object.shader.passes[0].srcBlend = trinity.TRIBLEND_SRCALPHA
            cloudTf.object.shader.passes[0].dstBlend = trinity.TRIBLEND_INVSRCALPHA
        else:
            cloudTf.object.shader.passes[0].fog = 0
        cloudTf.object.shader.writeZ = 0
        self.children.append(cloudTf)
        cloudTf.display = 0
        if (cloudType in ('constellationLines', 'currentConstellation')):
            cloudPoints = trinity.TriTransform()
            cloudPoints.name = (('__' + cloudType) + 'Points')
            cloudPoints.object = trinity.TriParticleCloud()
            cloudPoints.object.AnimateUV = trinity.TRTPA_64
            cloudPoints.pickable = 0
            cloudPoints.sorted = 0
            if (cloudType in ('lines', 'currentConstellation')):
                cloudPoints.object.cloudType = trinity.TRICT_POINT
                cloudPoints.object.shader = blue.os.LoadObject('res:/UI/Shader/particle_point.blue')
                cloudPoints.object.shader.zFunc = trinity.TRICMP_ALWAYS
                cloudPoints.object.shader.passes[0].textureStage0.colorOp = trinity.TRITOP_SELECTARG2
                cloudPoints.object.shader.passes[0].materialSource = trinity.TRIMATSRC_SHADER
                cloudPoints.object.shader.passes[0].srcBlend = trinity.TRIBLEND_SRCALPHA
                cloudPoints.object.shader.passes[0].dstBlend = trinity.TRIBLEND_ZERO
            else:
                cloudPoints.object.cloudType = trinity.TRICT_SPRITE
                cloudPoints.object.falloff = 1
                cloudPoints.object.shader = blue.os.LoadObject('res:/UI/Shader/particle_node2.blue')
            cloudPoints.object.shader.passes[0].materialSource = trinity.TRIMATSRC_SHADER
            del cloudPoints.object.shader.shaderMaterials[:]
            cloudPoints.object.shader.shaderMaterials.append(trinity.TriAniMaterial())
            cloudPoints.object.shader.shaderMaterials[0].emissive.SetRGB(0.65, 0.65, 0.65)
            cloudPoints.display = 1
            cloudTf.children.append(cloudPoints)
        if (cloudType == 'regionLines'):
            regionSprite = blue.os.LoadObject('res:/UI/Shared/Maps/maps_regionicon.blue')
            cloudTf.children.append(regionSprite)
            regionSprite.scaling.Scale(0.5)
            cloudTf.pickable = 1
            cloudTf.object.pickable = 0
            regionSprite.name = ('__regionDot' + str(self.sr.id))
        setattr(self.sr, cloudType, cloudTf)
        return cloudTf



    def GetLinesAndPoints(self, cloudType):
        if not self.sr.Get(cloudType):
            return self.CreateLinesAndPoints(cloudType)
        else:
            return self.sr.Get(cloudType)



    def GetColor(self):
        color = trinity.TriColor()
        color.SetHSV(((float(self.sr.id) * 21) % 360.0), 0.5, 0.8)
        color.a = 0.75
        return color



    def CreateLabels(self, labelids):
        for labelID in labelids:
            if self.sr.labels.has_key(labelID):
                continue
            if (labelID in self.sr.labels):
                label = self.sr.labels[labelID]
                if ((label is not None) and (not label.destroyed)):
                    continue
                else:
                    del self.sr.labels[labelID]
            self.AddLabel(labelID)




    def ClearLabels(self, labelids = 'all'):
        if (labelids == 'all'):
            labelids = self.sr.labels.keys()
        for labelID in labelids:
            if self.sr.labels.has_key(labelID):
                label = self.sr.labels[labelID]
                if ((label is not None) and (not label.destroyed)):
                    label.Close()
            del self.sr.labels[labelID]




    def AddLabel(self, itemID):
        iteminfo = sm.GetService('map').GetItem(itemID)
        if not iteminfo.itemName:
            return 
        tracker = self.AddTracker(iteminfo.itemName, iteminfo.itemID, iteminfo.x, iteminfo.y, iteminfo.z, self.sr.sizefactor)
        label = xtriui.MapLabel(trinity.UIBracket())
        label.name = 'label'
        label.align = uix.UI_ALABSOLUTE
        label.state = uix.UI_PICKCHILDREN
        label.width = 300
        label.height = 32
        label.Startup(iteminfo.itemName, iteminfo.itemID, iteminfo.typeID, tracker, self)
        uicore.layer.map.children.insert(0, label)
        self.sr.labels[itemID] = label



    def AddTracker(self, name, itemID, x = 0.0, y = 0.0, z = 0.0, factor = None):
        if (itemID in self.sr.trackers):
            return self.sr.trackers[itemID]
        else:
            tracker = xtriui.LabelTracker(trinity.TriTransform())
            tracker.Initialize(name, itemID)
            tracker.SetTranslation(x, y, z, factor)
            self.sr.labeltrackers.children.append(tracker)
            return tracker



    def UseFog(self, onoff = 1):
        return 
        self.object.shader.passes[0].fog = onoff
        self.sr.lines.object.shader.passes[0].fog = onoff



    def SetDisplay(self, model, display, animate, isSelected):
        if isSelected:
            alphaCurveUpToUse = alphaCurveUp.CopyTo()
            alphaDownCurveToUse = alphaCurveDown.CopyTo()
        else:
            alphaCurveUpToUse = alphaCurveUpHalf.CopyTo()
            alphaDownCurveToUse = alphaCurveDownHalf.CopyTo()
        if display:
            if model.display:
                mat = model.object.shader.shaderMaterials[0]
                curveToUse = alphaCurveUpToUse
                if mat.diffuseCurve:
                    curveToUse.keys[0].value = mat.diffuseCurve.GetColorAt(blue.os.GetTime(1))
                    curveToUse.keys[1].value = mat.diffuseCurve.GetColorAt(blue.os.GetTime(1))
                mat.diffuseCurve = curveToUse
                animate = 0
                if model.displayCurve:
                    model.displayCurve.keys[0].value = model.displayCurve.GetScalarAt(blue.os.GetTime())
                    model.displayCurve.keys[1].value = 1.0
                if model.scalingCurve:
                    model.scalingCurve.keys[0].value = model.scalingCurve.GetVectorAt(blue.os.GetTime())
                    model.scalingCurve.keys[1].value.SetXYZ(1.0, 1.0, 1.0)
                    model.scalingCurve.keys[2].value.SetXYZ(1.0, 1.0, 1.0)
            else:
                model.update = 0
                model.scalingCurve = scaleUpCurve.CopyTo()
                model.displayCurve = showCurve.CopyTo()
                model.object.shader.shaderMaterials[0].diffuseCurve = alphaCurveUpToUse.CopyTo()
        elif not model.display:
            return 
        model.update = 0
        model.object.shader.shaderMaterials[0].diffuseCurve = alphaDownCurveToUse
        if animate:
            model.scalingCurve = scaleDownCurve.CopyTo()
        else:
            model.scalingCurve = scaleUpCurve.CopyTo()
        model.displayCurve = hideCurve.CopyTo()
        if animate:
            model.scalingCurve.start = blue.os.GetTime()
        if model.displayCurve:
            model.displayCurve.start = blue.os.GetTime()
        model.object.shader.shaderMaterials[0].diffuseCurve.start = blue.os.GetTime()
        model.useCurves = 1
        model.update = 1
        if len(model.children):
            each = model.children[0]
            if hasattr(each.object, 'shader'):
                mat = each.object.shader.shaderMaterials[0]
            else:
                mat = each.object.areas[0].shader.shaderMaterials[0]
            if display:
                mat.diffuseCurve = alphaCurveUpToUse.CopyTo()
            elif mat.diffuseCurve:
                alphaDownCurveToUse.keys[0].value = mat.diffuseCurve.GetColorAt(blue.os.GetTime())
                alphaDownCurveToUse.keys[1].value = mat.diffuseCurve.GetColorAt(blue.os.GetTime())
            mat.diffuseCurve = alphaDownCurveToUse
            mat.diffuseCurve.start = blue.os.GetTime()



    def ShowLines(self, display, connectionViewMode, wasConnectionViewMode, isSelected):
        linesToDisplay = []
        if not display:
            linesToDisplay.append(('lines', 0, 1))
            linesToDisplay.append(('constellationLines', 0, 1))
            linesToDisplay.append(('regionLines', 0, 1))
            displayCurveToUse = hideCurve.CopyTo()
            if self.displayCurve:
                displayCurveToUse.keys[0].value = self.displayCurve.GetScalarAt(blue.os.GetTime())
            else:
                displayCurveToUse.keys[0].value = 0.0
            self.displayCurve = displayCurveToUse.CopyTo()
            self.displayCurve.start = blue.os.GetTime()
            self.useCurves = 1
        else:
            self.displayCurve = None
            self.display = 1
            if (connectionViewMode == MODE_NOLINES):
                linesToDisplay.append(('lines', 0, 1))
                linesToDisplay.append(('constellationLines', 0, 1))
                linesToDisplay.append(('regionLines', 0, 1))
            elif (connectionViewMode == MODE_REGION):
                linesToDisplay.append(('lines', 0, 1))
                linesToDisplay.append(('constellationLines', 0, 1))
                linesToDisplay.append(('regionLines', 1, 1))
            elif (connectionViewMode == MODE_CONSTELLATION):
                if ((wasConnectionViewMode == MODE_SOLARSYSTEM) or (wasConnectionViewMode == MODE_NOLINES)):
                    anim = 0
                else:
                    anim = 1
                linesToDisplay.append(('lines',
                 0,
                 anim))
                linesToDisplay.append(('constellationLines',
                 1,
                 anim))
                linesToDisplay.append(('regionLines', 0, 1))
            elif ((wasConnectionViewMode == MODE_CONSTELLATION) or (wasConnectionViewMode == MODE_NOLINES)):
                anim = 0
            else:
                anim = 1
            linesToDisplay.append(('lines',
             1,
             anim))
            linesToDisplay.append(('constellationLines',
             0,
             anim))
            linesToDisplay.append(('regionLines', 0, 1))
        for each in linesToDisplay:
            (modelName, display, animate,) = each
            if (modelName not in self.sr.isReady):
                if not display:
                    continue
                else:
                    sm.GetService('map').MakeLinesReady(modelName, self.sr.id)
            model = self.sr.Get(modelName)
            self.SetDisplay(model, display, animate, isSelected)





class LabelTracker(bluepy.WrapBlueClass('trinity.TriTransform')):
    __guid__ = 'xtriui.LabelTracker'
    __persistvars__ = ['sr']

    def __init__(self):
        self.sr = uiutil.Bunch()
        self.wr = util.WeakRefAttrObject()



    def Initialize(self, name, itemID):
        self.sr.itemID = itemID



    def SetTranslation(self, x = 0.0, y = 0.0, z = 0.0, factor = None):
        self.translation.SetXYZ(x, y, z)
        if factor:
            self.translation.Scale(factor)




